/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
  <file> uls_util.h </file>
  <brief>
    The utility routines in ULS.
    This file is part of ULS, Unified Lexical Scheme.
  </brief>
  <author>
    Stanley J. Hong <babel96@gmail.com>, 2011.
  </author>
*/
#ifndef __ULS_UTIL_H__
#define __ULS_UTIL_H__

#include "uls_type.h"
#include "uls_const.h"

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#ifdef __cplusplus
extern "C" {
#endif

#define FILEBUFF_SIZ  4095

#ifdef DEBUG
#define uls_assert(x) do { \
		if ((x)==0) \
			err_panic("assertion failed:%s:%d: '%s'\n", __FILE__, __LINE__, #x); \
	} while (0)
#else
#define uls_assert(x) 
#endif

#define BYTE_SIZE_LOG_BITS  3
#define BYTE_SIZE_BITS      (1<<BYTE_SIZE_LOG_BITS)
#define byte_ent_no(i_bit)  ((i_bit) >> BYTE_SIZE_LOG_BITS)
#define byte_offset(i_bit)  ((i_bit) & (BYTE_SIZE_BITS-1))
#define BYTE_LEFT_MOST_1    (1<<(BYTE_SIZE_BITS-1))

#define uls_set_bit(nr,addr)   ((*((uls_byte_t *) (addr) + ((nr)>>3) )) |=  (0x80 >> ((nr) & 0x07)) )
#define uls_clear_bit(nr,addr) ((*((uls_byte_t *) (addr) + ((nr)>>3) )) &= ~(0x80 >> ((nr) & 0x07)) )
#define uls_test_bit(nr,addr)  ((*((uls_byte_t *) (addr) + ((nr)>>3) )) &   (0x80 >> ((nr) & 0x07)) )

typedef int (*uls_optproc_t)(int opt, char* optarg);

int uls_mktemp(char* filepath, int filepath_siz);
int uls_movefile(char* fpath1, char* fpath2);
int uls_file_exist(char* filepath);

typedef int (*uls_bi_comp_t)(void* a, uls_char_t* kwrd);
void* uls_bi_search(uls_char_t* kwrd, void** ptr_ary, int n_ptr_ary,
	uls_bi_comp_t comp_func);

int is_octal_char(char ch);
int is_hexa_char(char ch);
uls_char_t read_hexa_char(uls_char_t* ptr);

int is_int_number(char* lptr);
unsigned int skip_atou(char** p_lptr);
unsigned int skip_atox(char** p_lptr);
int get_range_atou(char ** p_lptr, unsigned int *p_i1, unsigned int* p_i2);

char* skip_space_chars(char* lptr);
char* uls_filename(const char *filepath);
int uls_get_column_int(char* line, int* ptr_i);
int uls_get_column_words(char *line, char delim_ch, char** args, int n_args);

int uls_encode_utf8(uls_uch_t uch, uls_char_t* buff);
int uls_decode_utf8(uls_char_t *lptr, uls_uch_t *p_val);
int uls_dec_utf8(uls_char_t *lptr, uls_char_t *lptr_end, uls_uch_t *p_val);

uls_char_t* uls_skip_multiline_comment(uls_char_t* lptr, uls_char_t* lptr_end, int* num_nl);
uls_char_t* uls_skip_singleline_comment(uls_char_t* lptr, uls_char_t* lptr_end);

const char* uls_strchr_r(const char* lptr, char ch);
int uls_str_tolower(char* src, char *dst, int len);
int uls_str_toupper(char* src, char *dst, int len);
int uls_strcasecmp(const char* str1, const char* str2);

void* uls_malloc(unsigned int n_bytes);
void* uls_mrealloc(void* ptr, unsigned int n_bytes);
void* uls_mfree(void* ptr);

int uls_range_of_bits(uls_uint32 n);
void uls_clear_bits(uls_char_t* srcptr, uls_uint32 start_bit, uls_uint32 end_bit);
int uls_find_first_1bit(uls_char_t* srcptr,
	uls_uint32 start_bit, uls_uint32 end_bit, uls_uint32* found_bit);

uls_uch_t uls_get_escape_char(char** p_lptr);
int uls_get_escape_str(uls_char_t quote_ch, char* line, char* line2);

void uls_reverse_array(uls_char_t* ary, int n);
void get_current_time_yyyymmdd_hhmm(char* buf, int buf_siz);

int uls_readn(int fd, uls_char_t* ptr, int n);
int uls_writen(int fd, uls_char_t* ptr, int n);
int uls_readline(int fd, char* ptr, int n);

#ifdef ULS_LITTLE_ENDIAN 
#define arch2be_array(ary,n) uls_reverse_array(ary, n)
#define arch2le_array(ary,n)
#else
#define arch2be_array(ary,n)
#define arch2le_array(ary,n) uls_reverse_array(ary, n)
#endif

int uls_getopts(int n_args, char* args[], char* opt_str, uls_optproc_t proc);

char* is_cnst_suffix_contained(char* cstr_pool, const char* str, int l_str, char** p_end_ptr);
char* find_cnst_suffix(char* cstr_pool, const char* str, int l_str, char** p_end_ptr);
int add_cnst_suffix(char* cnst_suffixes, const char* suffix);

#ifdef __cplusplus
}
#endif

#endif 
